package com.springboot.sba.D9_DynamicTask.config;

import com.springboot.sba.D9_DynamicTask.bean.ScheduledVo;
import com.springboot.sba.D9_DynamicTask.dao.ScheduledMapper;
import com.springboot.sba.D9_DynamicTask.task.ScheduledTaskJob;
import com.springboot.sba.utils.SpringContextUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @description:
 * @author: ZZZ
 * @time: 2021/8/8 17:58
 */

@Slf4j
@Component
public class ScheduledTask2 {

    @Value("${task.enabled}")
    private Boolean taskEnable;

    /**
     * 可重入锁
     */
    private ReentrantLock lock = new ReentrantLock();
    /**
     * 定时任务线程池
     */
    @Autowired
    private ThreadPoolTaskScheduler threadPoolTaskScheduler;

    /**
     * 存放已经启动的任务map
     */
    private ConcurrentHashMap<String, ScheduledFuture> scheduledFutureMap = new ConcurrentHashMap<>();

    @Autowired
    private ScheduledMapper scheduledMapper;
    /**
     * 初始化  ==> 启动所有正常状态的任务
     */
    public void initAllTask() {
        if(!taskEnable){
            log.info("配置文件禁用了定时任务----");
            return;
        }
        List<ScheduledVo> scheduleds = scheduledMapper.queryAlL();
        log.info("初始化  ==> 启动所有正常状态的任务开始 ！size={}", scheduleds == null ? 0 : scheduleds.size());
        if (scheduleds == null || scheduleds.size() < 1) {
            return;
        }
        for (ScheduledVo scheduled : scheduleds) {
            //任务 key
            String taskKey = scheduled.getTaskKey();
            //校验是否已经启动
            if (this.isStart(taskKey)) {
                // 重启任务
                this.restart(taskKey,scheduled);
            } else {
                // 启动任务
                this.doStartTask(scheduled);
            }
        }
        log.info("初始化  ==> 启动所有正常状态的任务结束 ！");
    }

    //根据key 启动定时任务
    public Boolean start(String taskKey, ScheduledVo scheduled) {

        //添加锁放一个线程启动，防止多人启动多次

        log.info(">>>>>> 添加任务启动锁完毕");
        try {
            lock.lock();
            //校验是否已经启动
            if (this.isStart(taskKey)) {
                log.info(">>>>>> 当前任务已经启动，无需重复启动！");
                return false;
            }
            //查询配置
            if(scheduled == null) {
                scheduled = this.getByTaskKey(taskKey);
            }
            if(scheduled == null) {
                return false;
            }
            //启动任务
            this.doStartTask(scheduled);
        } finally {
            // 释放锁
            lock.unlock();
            log.info(">>>>>> 释放任务启动锁完毕");
        }
        log.info(">>>>>> 启动任务 {} 结束 >>>>>>", taskKey);
        return true;
    }

    //查询定时任务配置参数
    private ScheduledVo getByTaskKey(String taskKey) {
        /*ScheduledExample scheduledExample = new ScheduledExample();
        scheduledExample.createCriteria()
                .andStatusEqualTo(ScheduledStatus.DISABLE.getCode())
                .andTaskKeyEqualTo(taskKey);*/
        List<ScheduledVo> scheduleds = scheduledMapper.queryAlLByTaskKey(taskKey);
        if(scheduleds == null || scheduleds.size() < 1) {
            return null;
        }
        return scheduleds.get(0);
    }

    //根据 key 停止任务
    public Boolean stop(String taskKey) {
        log.info(">>>>>> 进入停止任务 {}  >>>>>>", taskKey);
        //当前任务实例是否存在
        boolean taskStartFlag = scheduledFutureMap.containsKey(taskKey);
        log.info(">>>>>> 当前任务实例是否存在 {}", taskStartFlag);
        if (taskStartFlag) {
            //获取任务实例
            ScheduledFuture scheduledFuture = scheduledFutureMap.get(taskKey);
            //关闭实例
            boolean cancel = scheduledFuture.cancel(true);
            log.info("cancel:{}", cancel);
            // 查看任务是否在正常执行之前结束,正常true
            boolean cancelled = scheduledFuture.isCancelled();
            while (!cancelled) {
                scheduledFuture.cancel(true);
            }
            //删除关闭的任务实例
            scheduledFutureMap.remove(taskKey);
        }
        log.info(">>>>>> 结束停止任务 {}  >>>>>>", taskKey);
        return taskStartFlag;
    }

    //根据任务key 重启任务
    public Boolean restart(String taskKey, ScheduledVo scheduled) {
        log.info(">>>>>> 进入重启任务 {}  >>>>>>", taskKey);
        //先停止
        this.stop(taskKey);
        //查询配置
        if(scheduled == null) {
            scheduled = this.getByTaskKey(taskKey);
        }
        if(scheduled == null) {
            return false;
        }
        //再启动
        return this.start(taskKey,scheduled);
    }



    /**
     * 执行启动任务
     */
    private void doStartTask(ScheduledVo scheduled) {
        if (scheduled == null) {
            return;
        }
        //任务key
        String taskKey = scheduled.getTaskKey();
        //定时表达式
        String taskCron = scheduled.getCron();
        //获取需要定时调度的接口
        ScheduledTaskJob scheduledTaskJob = (ScheduledTaskJob) SpringContextUtil.getBean(taskKey);
        log.info(">>>>>> 任务 [ {} ] ,cron={}", scheduled.getName(), taskCron);
       // ScheduledFuture scheduledFuture = threadPoolTaskScheduler.schedule(scheduledTaskJob, (TriggerContext triggerContext) -> new CronTrigger(taskCron).nextExecutionTime(triggerContext));
        ScheduledFuture scheduledFuture = threadPoolTaskScheduler.schedule(scheduledTaskJob, new CronTrigger(taskCron));
        //将启动的任务放入 map
        scheduledFutureMap.put(taskKey, scheduledFuture);
    }

    /**
     * 任务是否已经启动
     */
    private Boolean isStart(String taskKey) {
        //校验是否已经启动
        if (scheduledFutureMap.containsKey(taskKey)) {
            if (!scheduledFutureMap.get(taskKey).isCancelled()) {
                return true;
            }
        }
        return false;
    }

}


